package com.qh.pay.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableList;
import com.qh.common.config.CfgKeyConst;
import com.qh.common.excel.ImportExcel;
import com.qh.common.excel.annotation.QrConfig;
import com.qh.common.service.LocationService;
import com.qh.common.utils.*;
import com.qh.pay.api.Order;
import com.qh.pay.api.PayApi;
import com.qh.pay.api.constenum.OutChannel;
import com.qh.pay.api.constenum.PayCompany;
import com.qh.pay.api.constenum.UserType;
import com.qh.pay.api.utils.DateUtil;
import com.qh.pay.api.utils.ParamUtil;
import com.qh.pay.api.utils.Tesseract4JUtils;
import com.qh.pay.domain.FooterDO;
import com.qh.pay.domain.MoneyNum;
import com.qh.pay.domain.PayQrConfigDO;
import com.qh.pay.domain.QrsDO;
import com.qh.pay.service.PayQrConfigService;
import com.qh.redis.service.RedisUtil;
import com.qh.system.domain.UserDO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.validation.ConstraintViolationException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;

/**
 * 扫码通道配置
 *
 * @date 2017-12-14 14:37:38
 */

@Controller
@RequestMapping("/pay/payQrConfig")
public class PayQrConfigController {
    @Autowired
    private PayQrConfigService payQrConfigService;

    @Autowired
    private LocationService locationService;

    @GetMapping()
    @RequiresPermissions("pay:payQrConfig:payQrConfig")
    String PayQrConfig(Model model) {
//		model.addAttribute("payCompanys", PayCompany.jfDesc());
        model.addAttribute("outChannels", OutChannel.jfDesc());
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            model.addAttribute("ifMerch", "1");
            model.addAttribute("merchNo", user.getUsername());
        }

        return "pay/payQrConfig/payQrConfig";
    }


    @ResponseBody
    @GetMapping("/list")
    @RequiresPermissions("pay:payQrConfig:payQrConfig")
    public PageUtils list(@RequestParam Map<String, Object> params) {

        //查询列表数据
        Query query = new Query(params);
        UserDO user = ShiroUtils.getUser();
        List<PayQrConfigDO> payQrConfigList = payQrConfigService.list(query);
        if (ShiroUtils.ifMerch(user)) {
            query.put("merchNo", user.getUsername());
            for (PayQrConfigDO payQrConfigDO : payQrConfigList) {
                payQrConfigDO.setCostRate(null);
            }
        }

        int total = payQrConfigService.count(query);
        PageUtils pageUtils = new PageUtils(payQrConfigList, total);
        return pageUtils;
    }

    @GetMapping("/list/numPage")
    @RequiresPermissions("pay:payQrConfig:payQrConfig")
    String PayQrConfigNumPage(Model model) {
        return "pay/payQrConfig/payQrConfigNum";
    }

    @ResponseBody
    @GetMapping("/list/num")
    @RequiresPermissions("pay:payQrConfig:payQrConfig")
    public PageUtils listNum(@RequestParam Map<String, Object> params) {

        List<MoneyNum> list = RedisUtil.getMonAmountNum(OutChannel.ali.name());

        PageUtils pageUtils = new PageUtils(list, list.size());
        return pageUtils;
    }

    @GetMapping("/add")
    @RequiresPermissions("pay:payQrConfig:add")
    String add(Model model) {
        model.addAttribute("payCompanys", PayCompany.jfDesc());
        model.addAttribute("outChannels", OutChannel.jfDesc());
        model.addAttribute("provinces", locationService.listProvinces());
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            model.addAttribute("merchNo", user.getUsername());
        }
        return "pay/payQrConfig/add";
    }

    @GetMapping("/edit/{id}")
    @RequiresPermissions("pay:payQrConfig:edit")
    String edit(@PathVariable("id") String id, Model model) {

        model.addAttribute("provinces", locationService.listProvinces());
        model.addAttribute("outChannels", OutChannel.jfDesc());
        UserDO user = ShiroUtils.getUser();
        if (!ShiroUtils.ifMerch(user)) {
            PayQrConfigDO payQrConfig = payQrConfigService.get(Integer.valueOf(id));
            model.addAttribute("payQrConfig", payQrConfig);
        }
        return "pay/payQrConfig/edit";
    }

    @ResponseBody
    @PostMapping("/getQrs/{outChannel}/{merchNo}/{accountNo}")
    @RequiresPermissions("pay:payQrConfig:upload")
    R getQrs(@PathVariable("outChannel") String outChannel, @PathVariable("merchNo") String merchNo,
             @PathVariable("accountNo") String accountNo) {
        UserDO user = ShiroUtils.getUser();
        if (!ShiroUtils.ifMerch(user) || merchNo.equals(user.getUsername())) {
            PayQrConfigDO payQrConfig = payQrConfigService.get(outChannel, accountNo);
            return R.okData(payQrConfig);
        }
        return R.error("获取图片二维码失败！");
    }

    /**
     * 保存
     */
    @ResponseBody
    @PostMapping("/save")
    @RequiresPermissions("pay:payQrConfig:add")
    public R save(PayQrConfigDO payQrConfig) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        if (payQrConfig.getStatus() > 23) {
            return R.error("有效时长不能超过23");
        }
        int flag = PayApi.pay(payQrConfig);
        if (flag == 1) {
            try {
                int count = payQrConfigService.save(payQrConfig);
                if (count == 1) {
                    return R.ok();
                } else {
                    return R.error("该通道已配置");
                }
            } catch (Exception e) {
                e.printStackTrace();
                return R.error("该通道已配置");
            }


        } else if (flag == 0) {
            return R.error("旺旺号和订单号不匹配或者店铺未授权");
        } else if (flag == 2) {
            return R.error("订单已支付");
        } else if (flag == 3) {
            return R.error("订单状态异常");
        } else {
            return R.error("未知异常");
        }

    }

    /**
     * 修改
     */
    @ResponseBody
    @RequestMapping("/update")
    @RequiresPermissions("pay:payQrConfig:edit")
    public R update(PayQrConfigDO payQrConfig) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        if (payQrConfig.getStatus() > 23) {
            return R.error("有效时长不能超过23");
        }
        payQrConfigService.update(payQrConfig);
        return R.ok();
    }

    @ResponseBody
    @RequestMapping("/updateQrs")
    @RequiresPermissions("pay:payQrConfig:edit")
    public R updateQrs(PayQrConfigDO payQrConfig) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        payQrConfigService.updateQrs(payQrConfig);
        return R.ok();
    }

    @ResponseBody
    @RequestMapping("/updateQrUse")
    @RequiresPermissions("pay:payQrConfig:edit")
    public R updateQrUse(String id, String flag) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        PayQrConfigDO p = payQrConfigService.get(Integer.parseInt(id));
        payQrConfigService.updateQrUseState(flag, p.getAccountNo(), p.getOutChannel(),
                ParamUtil.subZeroAndDot(String.valueOf(p.getMoney())));
        return R.ok();
    }

    /**
     * 删除
     */
    @PostMapping("/remove")
    @ResponseBody
    @RequiresPermissions("pay:payQrConfig:remove")
    public R remove(@RequestParam("id") String id) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        if (payQrConfigService.remove(id) > 0) {
            return R.ok();
        }
        return R.error();
    }


    @PostMapping("/syncs")
    @ResponseBody
    @RequiresPermissions("pay:payQrConfig:remove")
    public R syncs(@RequestParam("id") String id) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user)) {
            return R.error("权限错误");
        }
        int i = payQrConfigService.updatePay(id);
        if (i == -1) {
            return R.error("订单已同步");
        } else {
            return R.ok("同步成功");
        }


    }

    @GetMapping("/editQrs/{outChannel}/{accountNo}")
    @RequiresPermissions("pay:payQrConfig:upload")
    String editQrs(@PathVariable("outChannel") String outChannel,
                   @PathVariable("accountNo") String accountNo, Model model) {
        model.addAttribute("payCompanys", PayCompany.jfDesc());
        model.addAttribute("outChannels", OutChannel.jfDesc());
        UserDO user = ShiroUtils.getUser();
        if (!ShiroUtils.ifMerch(user)) {
            PayQrConfigDO payQrConfig = payQrConfigService.get(outChannel, accountNo);
            JSONArray array = JSONArray.parseArray(payQrConfig.getQrs());
            ArrayList<HashMap> list = new ArrayList<>();
            for (int i = 0; i < array.size(); i++) {
                HashMap<String, String> hashMap = new HashMap<>();
                hashMap.put("money", array.getJSONObject(i).getString("money"));
                hashMap.put("qrs", array.getJSONObject(i).getString("qrs"));

                list.add(hashMap);
            }

            model.addAttribute("payQrConfig", payQrConfig);
            model.addAttribute("qrList", list);
            model.addAttribute("num", list.size());
        }
        return "pay/payQrConfig/editQr";
    }


    /**
     * @param outChannel
     * @param merchNo
     * @param file
     * @return
     * @Description 批量上传二维码图片
     */
    @ResponseBody
    @PostMapping("/batchUploadQrs/{outChannel}/{merchNo}/{accountNo}")
    @RequiresPermissions("pay:payQrConfig:upload")
    R batchUploadQrs(@PathVariable("outChannel") String outChannel, @PathVariable("merchNo") String merchNo,
                     @PathVariable("accountNo") String accountNo, @RequestParam("file") MultipartFile file) throws Exception {
        UserDO user = ShiroUtils.getUser();
        R r = new R();
        if (ShiroUtils.ifMerch(user) && !user.getUsername().equals(merchNo)) {
            return R.error("权限错误");
        }

        String moneyAmount = "";
//        if (OutChannel.jfwx.name().equals(outChannel)) {
//            moneyAmount = Tesseract4JUtils.doWxQrMoneyOcr(ImageIO.read(new ByteArrayInputStream(file.getBytes())));
//        } else if (OutChannel.jfali.name().equals(outChannel)) {
//            moneyAmount = Tesseract4JUtils.doAliQrMoneyOcr(ImageIO.read(new ByteArrayInputStream(file.getBytes())));
//        }

        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
        if (!FileType.ifPicType(fileType) || !fileType.endsWith("jpg")) {
            r.put("error", "请上传收款二维码图片");
            return r;
        }
        if (file.getSize() > 5 * 100 * 1024) {
            r.put("error", "请上传大小500K以内的图片");
            return r;
        }

        moneyAmount = ParamUtil.subZeroAndDot(moneyAmount);
        if (!moneyAmount.matches("\\d*.?\\d*")) {
            r.put("error", "请上传正确的二维码图片");
            return r;
        }

        r = payQrConfigService.updateQrs(outChannel, accountNo, moneyAmount);

        if (R.ifSucc(r)) {
            try {
                FileUtil.uploadFile(file.getBytes(),
                        RedisUtil.getSysConfigValue(CfgKeyConst.qr_money_path) + merchNo + File.separator + outChannel + File.separator + accountNo + File.separator,
                        moneyAmount.replace(".", "p") + "." + fileType);
            } catch (Exception e) {
                r.put("error", "文件上传失败！");
                return r;
            }
        }
        if (R.ifError(r)) {
            r.put("error", r.getMsg());
        }

        return r;
    }

    /**
     * @param outChannel
     * @param merchNo
     * @param moneyAmount
     * @param file
     * @return
     * @Description 上传二维码图片
     */
    @ResponseBody
    @PostMapping("/uploadQrs/{outChannel}/{merchNo}/{accountNo}")
    @RequiresPermissions("pay:payQrConfig:upload")
    R uploadQrs(@PathVariable("outChannel") String outChannel, @PathVariable("merchNo") String merchNo,
                @PathVariable("accountNo") String accountNo, @RequestParam("moneyAmount") String moneyAmount,
                @RequestParam("file") MultipartFile file) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user) && !user.getUsername().equals(merchNo)) {
            return R.error("权限错误");
        }
        if (ParamUtil.isEmpty(moneyAmount)) {
            return R.error("请输入二维收款码金额");
        }
        String fileName = file.getOriginalFilename();
        String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase();
        if (!FileType.ifPicType(fileType) || !fileType.endsWith("jpg")) {
            return R.error("请上传收款二维码图片");
        }
        if (file.getSize() > 2 * 100 * 1024) {
            return R.error("请上传大小200K以内的图片");
        }

        moneyAmount = ParamUtil.subZeroAndDot(moneyAmount);
        R r = payQrConfigService.updateQrs(outChannel, accountNo, moneyAmount);
        if (R.ifSucc(r)) {
            try {
                FileUtil.uploadFile(file.getBytes(),
                        RedisUtil.getSysConfigValue(CfgKeyConst.qr_money_path) + merchNo + File.separator + outChannel + File.separator + accountNo + File.separator,
                        moneyAmount.replace(".", "p") + "." + fileType);
            } catch (Exception e) {
                return R.error("文件上传失败！");
            }
        }
        return r;
    }

    private void deleteFile(File... files) {
        for (File file : files) {
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * @return
     * @Description 批量上传代付码
     */
    @ResponseBody
    @PostMapping("/uploadQrs/taobaofile")
    @RequiresPermissions("pay:payQrConfig:upload")
    R uploadQrsTaobaoFile(
            @RequestParam("file") MultipartFile file) {

        File excelFile = null;
        try {
            int successNum = 0;
            int failureNum = 0;
            StringBuilder failureMsg = new StringBuilder();

            // 获取文件名
            String fileName = file.getOriginalFilename();

            // 获取文件后缀
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            String name = fileName.substring(0,fileName.lastIndexOf("."));

            // 用uuid作为文件名，防止生成的临时文件重复
            excelFile = File.createTempFile(name, prefix);
            // MultipartFile to File
            file.transferTo(excelFile);
            //解压文件
            ZipUtil.unZip( excelFile, "c://qrs");
//            List<QrConfig> list = new ArrayList<>();
            List<QrConfig> list = ZipUtil.scan("c://qrs/"+name,name);
            for (QrConfig qrConfig : list) {
                try {
                    int i = saves(qrConfig.getOrder(), qrConfig.getName(), qrConfig.getQrs());
                    if (i == 1) {
                        successNum++;
                    } else {
                        if (i == 200) {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：已存在");
                        } else if (i == 0) {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：旺旺号和订单号不匹配或者店铺未授权");
                        } else if (i == 2) {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：订单已支付");
                        } else if (i == 3) {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：订单状态异常");
                        } else {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：未知异常");
                        }
                    }
                } catch (Exception ex) {
                    failureMsg.append("<br/>订单号" + " 导入失败：" + ex.getMessage());
                }
            }
            if (failureNum > 0) {
                failureMsg.insert(0, "，失败 " + failureNum + " 条，导入信息如下：");
            }
            return R.ok("已成功导入 " + successNum + " 条" + failureMsg);
        } catch (Exception e) {
            e.printStackTrace();
            return R.ok("导入失败！失败信息：" + e.getMessage());
        } finally {
            deleteFile(excelFile);

        }
    }

    /**
     * @return
     * @Description 批量上传代付码
     */
    @ResponseBody
    @PostMapping("/uploadQrs/taobao")
    @RequiresPermissions("pay:payQrConfig:upload")
    R uploadQrsTaobao(
            @RequestParam("file") MultipartFile file) {

        try {
            int successNum = 0;
            int failureNum = 0;
            StringBuilder failureMsg = new StringBuilder();
            ImportExcel ei = new ImportExcel(file, 1, 0);
            List<QrConfig> list = ei.getDataList(QrConfig.class);
            for (QrConfig qrConfig : list) {

                try {
                    int i = saves(qrConfig.getOrder(), qrConfig.getName(), qrConfig.getQrs());
                    if (i == 1) {
                        successNum++;
                    } else {
                        if (i == 200) {

                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：已存在");
                        } else if (i == 0) {

                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：旺旺号和订单号不匹配或者店铺未授权");

                        } else if (i == 2) {

                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：订单已支付");

                        } else if (i == 3) {

                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：订单状态异常");

                        } else {
                            failureMsg.append("<br/>订单号" + qrConfig.getOrder() + " 导入失败：未知异常");
                        }

                    }

                } catch (Exception ex) {
                    failureMsg.append("<br/>订单号" + " 导入失败：" + ex.getMessage());
                }
            }
            if (failureNum > 0) {
                failureMsg.insert(0, "，失败 " + failureNum + " 条，导入信息如下：");
            }
            return R.ok("已成功导入 " + successNum + " 条" + failureMsg);
        } catch (Exception e) {
            return R.ok("导入失败！失败信息：" + e.getMessage());
        }
    }


    private int saves(String orderNO, String orderName, String qrs) {
        PayQrConfigDO payQrConfigDO = new PayQrConfigDO();
        payQrConfigDO.setOutChannel(OutChannel.ali.name());
        payQrConfigDO.setAccountNo(orderNO);
        payQrConfigDO.setAccountName(orderName);
        payQrConfigDO.setQrs(qrs);
        payQrConfigDO.setCostRate(BigDecimal.ZERO);
        int flag = PayApi.pay(payQrConfigDO);
        if (flag == 1) {
            try {
                int count = payQrConfigService.save(payQrConfigDO);
                if (count == 1) {
                    return 1;
                } else {
                    return 200;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return flag;

    }

    /**
     * @param outChannel
     * @param merchNo
     * @param moneyAmounts
     * @return
     * @Description 删除二维码收款图片
     */
    @ResponseBody
    @PostMapping("/removeQrs/{outChannel}/{merchNo}/{accountNo}")
    @RequiresPermissions("pay:payQrConfig:upload")
    R removeQrs(@PathVariable("outChannel") String outChannel, @PathVariable("merchNo") String merchNo,
                @PathVariable("accountNo") String accountNo, @RequestParam("moneyAmounts[]") String[] moneyAmounts) {
        UserDO user = ShiroUtils.getUser();
        if (ShiroUtils.ifMerch(user) && !user.getUsername().equals(merchNo)) {
            return R.error("权限错误");
        }

        R r = payQrConfigService.removeQrs(outChannel, accountNo, Arrays.asList(moneyAmounts));
        if (R.ifSucc(r)) {
            for (String moneyAmount : moneyAmounts) {
                moneyAmount = ParamUtil.subZeroAndDot(moneyAmount);
                FileUtil.deleteFile(RedisUtil.getSysConfigValue(CfgKeyConst.qr_money_path) + merchNo + File.separator + outChannel + File.separator + accountNo + File.separator +
                        moneyAmount.replace(".", "p") + ".jpg");
            }
        }
        return r;
    }

}
